From: kaf24@scramble.cl.cam.ac.uk Date: Sun, 28 Mar 2004 20:22:50 +0000 (+0000) Subject: bitkeeper revision 1.825.3.13 (4067341aEVBylJ8rvZlNJ-_l5YeAoQ) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~18253^2~8 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=3f211155ec8df4dc24918334dec511ea2595a570;p=xen.git bitkeeper revision 1.825.3.13 (4067341aEVBylJ8rvZlNJ-_l5YeAoQ) mkbuildtree, pci-pc.c, Makefile, defconfig-physdev, physdev.h, physdev.c: PCI-access updates for new IO world. .del-pci-irq.c~626134b3f85d1f48: Delete: xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c .del-pci-i386.h~17514121c175844: Delete: xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h .del-pci-i386.c~d13b1a4728189770: Delete: xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c --- diff --git a/.rootkeys b/.rootkeys index ee5806cabe..7a74d6af0b 100644 --- a/.rootkeys +++ b/.rootkeys @@ -639,9 +639,6 @@ 3e5a4e653U6cELGv528IxOLHvCq8iA xenolinux-2.4.25-sparse/arch/xen/kernel/irq.c 3e5a4e65muT6SU3ck47IP87Q7Ti5hA xenolinux-2.4.25-sparse/arch/xen/kernel/ldt.c 4051db84bZeRX7a_Kh6VyyDuT5FOIg xenolinux-2.4.25-sparse/arch/xen/kernel/pci-dma.c -4051db89iiHs38tWGkoW_RukNyaBHw xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c -4051db8dJYX86ZCLA-WfTW2dAyrehw xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h -4051db91BenvDZEMZxQCGkQyJYoG5w xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c 4051db95N9N99FjsRwi49YKUNHWI8A xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c 3e5a4e65IGt3WwQDNiL4h-gYWgNTWQ xenolinux-2.4.25-sparse/arch/xen/kernel/process.c 3e5a4e66tR-qJMLj3MppcKqmvuI2XQ xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c diff --git a/xen/common/physdev.c b/xen/common/physdev.c index 11746785f3..a3f3fb7f52 100644 --- a/xen/common/physdev.c +++ b/xen/common/physdev.c @@ -1,11 +1,8 @@ /* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- **************************************************************************** - * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge + * (c) 2004 - Rolf Neugebauer - Intel Research Cambridge + * (c) 2004 - Keir Fraser - University of Cambridge **************************************************************************** - * - * File: phys_dev.c - * Author: Rolf Neugebauer (rolf.neugebauer@intel.com) - * Date: Feb 2004 * * Description: allows a domain to access devices on the PCI bus * @@ -47,6 +44,9 @@ #include #include +/* Called by PHYSDEV_PCI_INITIALISE_DEVICE to finalise IRQ routing. */ +extern void pcibios_enable_irq(struct pci_dev *dev); + #if 1 #define DBG(_x...) #else @@ -267,7 +267,7 @@ inline static int check_dev_acc (struct task_struct *p, * error is flagged. */ static int do_base_address_access(phys_dev_t *pdev, int acc, - int seg, int bus, int dev, int func, + int bus, int dev, int func, int reg, int len, u32 *val) { int idx, st_bit, ret = -EINVAL; @@ -293,7 +293,7 @@ static int do_base_address_access(phys_dev_t *pdev, int acc, clear_bit(st_bit, &pdev->state); /* check if guest tries to restore orig value */ - ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val); + ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val); if ( *val != orig_val ) { printk("caution: guest tried to change base address range.\n"); @@ -311,12 +311,12 @@ static int do_base_address_access(phys_dev_t *pdev, int acc, if ( !test_bit(st_bit, &pdev->state) ) { /* just read and return */ - ret = pci_config_read(seg, bus, dev, func, reg, len, val); + ret = pci_config_read(0, bus, dev, func, reg, len, val); } else { /* fake value */ - ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val); + ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val); sz = res->end - res->start; @@ -358,8 +358,8 @@ static int do_base_address_access(phys_dev_t *pdev, int acc, * pretty much the same as a above */ static int do_rom_address_access(phys_dev_t *pdev, int acc, - int seg, int bus, int dev, int func, - int reg, int len, u32 *val) + int bus, int dev, int func, + int reg, int len, u32 *val) { int st_bit, ret = -EINVAL; u32 orig_val, sz; @@ -383,7 +383,7 @@ static int do_rom_address_access(phys_dev_t *pdev, int acc, clear_bit(st_bit, &pdev->state); /* check if guest tries to restore orig value */ - ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val); + ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val); if ( (*val != orig_val) ) { if (*val != 0x00000000 ) @@ -409,12 +409,12 @@ static int do_rom_address_access(phys_dev_t *pdev, int acc, if ( !test_bit(st_bit, &pdev->state) ) { /* just read and return */ - ret = pci_config_read(seg, bus, dev, func, reg, len, val); + ret = pci_config_read(0, bus, dev, func, reg, len, val); } else { /* fake value */ - ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val); + ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val); sz = res->end - res->start; *val = 0xffffffff; /* leave bit 0 untouched */ @@ -438,18 +438,17 @@ static int do_rom_address_access(phys_dev_t *pdev, int acc, * For some registers for read-only devices (e.g. address base registers) * we need to maintain a state machine. */ -static long pci_cfgreg_read(int seg, int bus, int dev, int func, int reg, +static long pci_cfgreg_read(int bus, int dev, int func, int reg, int len, u32 *val) { - int ret = 0; + int ret; phys_dev_t *pdev; - ret = check_dev_acc(current, bus, dev, func, &pdev); - if ( ret != 0 ) + if ( (ret = check_dev_acc(current, bus, dev, func, &pdev)) != 0 ) return ret; - /* fake out read requests for some registers */ - switch (reg) + /* Fake out read requests for some registers. */ + switch ( reg ) { case PCI_BASE_ADDRESS_0: case PCI_BASE_ADDRESS_1: @@ -457,23 +456,26 @@ static long pci_cfgreg_read(int seg, int bus, int dev, int func, int reg, case PCI_BASE_ADDRESS_3: case PCI_BASE_ADDRESS_4: case PCI_BASE_ADDRESS_5: - ret = do_base_address_access (pdev, ACC_READ, seg, bus, dev, - func, reg, len, val); - return ret; + ret = do_base_address_access(pdev, ACC_READ, bus, dev, + func, reg, len, val); break; + case PCI_ROM_ADDRESS: - ret = do_rom_address_access (pdev, ACC_READ, seg, bus, dev, - func, reg, len, val); - return ret; + ret = do_rom_address_access(pdev, ACC_READ, bus, dev, + func, reg, len, val); break; + + case PCI_INTERRUPT_LINE: + ret = pdev->dev->irq; + break; + default: + ret = pci_config_read(0, bus, dev, func, reg, len, val); + DBG("pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n", + bus, dev, func, reg, len, *val); break; } - ret = pci_config_read(seg, bus, dev, func, reg, len, val); - - DBG("pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n", - bus, dev, func, reg, len, *val); return ret; } @@ -483,14 +485,13 @@ static long pci_cfgreg_read(int seg, int bus, int dev, int func, int reg, * for some registers a state machine is maintained to fake out r/w access. * By default no write access is allowed but we may change that in the future. */ -static long pci_cfgreg_write(int seg, int bus, int dev, int func, int reg, +static long pci_cfgreg_write(int bus, int dev, int func, int reg, int len, u32 val) { - int ret = 0; + int ret; phys_dev_t *pdev; - ret = check_dev_acc(current, bus, dev, func, &pdev); - if ( ret != 0 ) + if ( (ret = check_dev_acc(current, bus, dev, func, &pdev)) != 0 ) return ret; /* special treatment for some registers */ @@ -502,73 +503,61 @@ static long pci_cfgreg_write(int seg, int bus, int dev, int func, int reg, case PCI_BASE_ADDRESS_3: case PCI_BASE_ADDRESS_4: case PCI_BASE_ADDRESS_5: - ret = do_base_address_access (pdev, ACC_WRITE, seg, bus, dev, + ret = do_base_address_access (pdev, ACC_WRITE, bus, dev, func, reg, len, &val); return ret; break; + case PCI_ROM_ADDRESS: - ret = do_rom_address_access (pdev, ACC_WRITE, seg, bus, dev, + ret = do_rom_address_access (pdev, ACC_WRITE, bus, dev, func, reg, len, &val); return ret; break; -#if 0 - case 0xe0: /* XXX some device drivers seem to write to this.... */ - printk("pci write hack allowed %02x:%02x:%02x: " - "reg=0x%02x len=0x%02x val=0x%08x\n", - bus, dev, func, reg, len, val); - break; -#endif + default: - //if ( pdev->flags != ACC_WRITE ) - /* XXX for debug we disallow all write access */ + if ( pdev->flags != ACC_WRITE ) { printk("pci write not allowed %02x:%02x:%02x: " "reg=0x%02x len=0x%02x val=0x%08x\n", bus, dev, func, reg, len, val); - return -EPERM; + ret = -EPERM; + } + else + { + ret = pci_config_write(0, bus, dev, func, reg, len, val); + DBG("pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n", + bus, dev, func, reg, len, val); } break; } - ret = pci_config_write(seg, bus, dev, func, reg, len, val); - - DBG("pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n", - bus, dev, func, reg, len, val); return ret; } -/* - * - * Interrupt handling - * - */ - -/* - * return the IRQ xen assigned to the device. - * This may be different to what is in the PCI confic space! - * XXX RN: I'm not sure we need this. we could just intercept PCI config - * reads on PCI_INTERRUPT_LINE and return the correct value. - */ -static long pci_find_irq(int seg, int bus, int dev, int func, u32 *val) +static long pci_probe_root_buses(u32 *busmask) { - int ret = 0; phys_dev_t *pdev; + struct list_head *tmp; - ret = check_dev_acc(current, bus, dev, func, &pdev); - if ( ret != 0 ) - return ret; + memset(busmask, 0, 256/8); + + list_for_each ( tmp, ¤t->pcidev_list ) + { + pdev = list_entry(tmp, phys_dev_t, node); + set_bit(pdev->dev->bus->number, busmask); + } - *val = pdev->dev->irq; return 0; } /* - * demux hypervisor call. + * Demuxing hypercall. */ long do_physdev_op(physdev_op_t *uop) { + phys_dev_t *pdev; physdev_op_t op; long ret; @@ -577,24 +566,35 @@ long do_physdev_op(physdev_op_t *uop) switch ( op.cmd ) { - case PHYSDEVOP_CFGREG_READ: - ret = pci_cfgreg_read(op.u.cfg_read.seg, op.u.cfg_read.bus, - op.u.cfg_read.dev, op.u.cfg_read.func, - op.u.cfg_read.reg, op.u.cfg_read.len, - &op.u.cfg_read.value); + case PHYSDEVOP_PCI_CFGREG_READ: + ret = pci_cfgreg_read(op.u.pci_cfgreg_read.bus, + op.u.pci_cfgreg_read.dev, + op.u.pci_cfgreg_read.func, + op.u.pci_cfgreg_read.reg, + op.u.pci_cfgreg_read.len, + &op.u.pci_cfgreg_read.value); break; - case PHYSDEVOP_CFGREG_WRITE: - ret = pci_cfgreg_write(op.u.cfg_write.seg, op.u.cfg_write.bus, - op.u.cfg_write.dev, op.u.cfg_write.func, - op.u.cfg_write.reg, op.u.cfg_write.len, - op.u.cfg_write.value); + case PHYSDEVOP_PCI_CFGREG_WRITE: + ret = pci_cfgreg_write(op.u.pci_cfgreg_write.bus, + op.u.pci_cfgreg_write.dev, + op.u.pci_cfgreg_write.func, + op.u.pci_cfgreg_write.reg, + op.u.pci_cfgreg_write.len, + op.u.pci_cfgreg_write.value); break; - case PHYSDEVOP_FIND_IRQ: - ret = pci_find_irq(op.u.find_irq.seg, op.u.find_irq.bus, - op.u.find_irq.dev, op.u.find_irq.func, - &op.u.find_irq.irq); + case PHYSDEVOP_PCI_INITIALISE_DEVICE: + if ( (ret = check_dev_acc(current, + op.u.pci_initialise_device.bus, + op.u.pci_initialise_device.dev, + op.u.pci_initialise_device.func, + &pdev)) == 0 ) + pcibios_enable_irq(pdev->dev); + break; + + case PHYSDEVOP_PCI_PROBE_ROOT_BUSES: + ret = pci_probe_root_buses(op.u.pci_probe_root_buses.busmask); break; case PHYSDEVOP_UNMASK_IRQ: @@ -611,10 +611,7 @@ long do_physdev_op(physdev_op_t *uop) } -/* - * Domain 0 has read access to all devices. - * XXX this is a bit of a hack - */ +/* Domain 0 has read access to all devices. */ void physdev_init_dom0(struct task_struct *p) { struct pci_dev *dev; @@ -627,7 +624,7 @@ void physdev_init_dom0(struct task_struct *p) /* add device */ pdev = kmalloc(sizeof(phys_dev_t), GFP_KERNEL); pdev->dev = dev; - pdev->flags = ACC_READ; + pdev->flags = ACC_WRITE; pdev->state = 0; pdev->owner = p; list_add(&pdev->node, &p->pcidev_list); diff --git a/xen/include/hypervisor-ifs/physdev.h b/xen/include/hypervisor-ifs/physdev.h index 383bb13097..914a555981 100644 --- a/xen/include/hypervisor-ifs/physdev.h +++ b/xen/include/hypervisor-ifs/physdev.h @@ -1,70 +1,66 @@ /* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- **************************************************************************** - * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge + * (c) 2004 - Rolf Neugebauer - Intel Research Cambridge + * (c) 2004 - Keir Fraser - University of Cambridge **************************************************************************** - * - * File: physdev.h - * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) - * Date: Feb 2004 - * * Description: Interface for domains to access physical devices on the PCI bus */ #ifndef __HYPERVISOR_IFS_PHYSDEV_H__ #define __HYPERVISOR_IFS_PHYSDEV_H__ -/* - * Commands to HYPERVISOR_physdev_op() - */ -#define PHYSDEVOP_CFGREG_READ 0 -#define PHYSDEVOP_CFGREG_WRITE 1 -#define PHYSDEVOP_FIND_IRQ 2 -#define PHYSDEVOP_UNMASK_IRQ 3 +/* Commands to HYPERVISOR_physdev_op() */ +#define PHYSDEVOP_PCI_CFGREG_READ 0 +#define PHYSDEVOP_PCI_CFGREG_WRITE 1 +#define PHYSDEVOP_PCI_INITIALISE_DEVICE 2 +#define PHYSDEVOP_PCI_PROBE_ROOT_BUSES 3 +#define PHYSDEVOP_UNMASK_IRQ 4 -/* read pci config */ -typedef struct physdevop_cfgreg_read_st +/* Read from PCI configuration space. */ +typedef struct physdevop_pci_cfgreg_read_st { - int seg; /* IN */ int bus; /* IN */ int dev; /* IN */ int func; /* IN */ int reg; /* IN */ int len; /* IN */ u32 value; /* OUT */ -} physdevop_cfgreg_read_t; +} physdevop_pci_cfgreg_read_t; -/* write pci config */ -typedef struct physdevop_cfgred_write_st +/* Write to PCI configuration space. */ +typedef struct physdevop_pci_cfgreg_write_st { - int seg; /* IN */ int bus; /* IN */ int dev; /* IN */ int func; /* IN */ int reg; /* IN */ int len; /* IN */ u32 value; /* IN */ -} physdevop_cfgreg_write_t; +} physdevop_pci_cfgreg_write_t; -/* get the real IRQ for a device */ -typedef struct physdevop_find_irq_st +/* Do final initialisation of a PCI device (e.g., last-moment IRQ routing). */ +typedef struct physdevop_pci_initialise_device_st { - int seg; /* IN */ int bus; /* IN */ int dev; /* IN */ int func; /* IN */ - u32 irq; /* OUT */ -} physdevop_find_irq_t; +} physdevop_pci_initialise_device_t; + +/* Find the root buses for subsequent scanning. */ +typedef struct physdevop_pci_probe_root_buses_st +{ + u32 busmask[256/32]; /* OUT */ +} physdevop_pci_probe_root_buses_t; typedef struct _physdev_op_st { unsigned long cmd; - - /* command parameters */ union { - physdevop_cfgreg_read_t cfg_read; - physdevop_cfgreg_write_t cfg_write; - physdevop_find_irq_t find_irq; + physdevop_pci_cfgreg_read_t pci_cfgreg_read; + physdevop_pci_cfgreg_write_t pci_cfgreg_write; + physdevop_pci_initialise_device_t pci_initialise_device; + physdevop_pci_probe_root_buses_t pci_probe_root_buses; } u; } physdev_op_t; diff --git a/xenolinux-2.4.25-sparse/arch/xen/defconfig-physdev b/xenolinux-2.4.25-sparse/arch/xen/defconfig-physdev index 52922f5bf1..e6a213757c 100644 --- a/xenolinux-2.4.25-sparse/arch/xen/defconfig-physdev +++ b/xenolinux-2.4.25-sparse/arch/xen/defconfig-physdev @@ -370,9 +370,9 @@ CONFIG_CHR_DEV_SG=y # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set -CONFIG_SCSI_AHA152X=y -CONFIG_SCSI_AHA1542=y -CONFIG_SCSI_AHA1740=y +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set CONFIG_SCSI_AACRAID=y # CONFIG_SCSI_AIC7XXX is not set CONFIG_SCSI_AIC79XX=y @@ -400,9 +400,9 @@ CONFIG_SCSI_DTC3280=y # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -CONFIG_SCSI_GENERIC_NCR5380=y +# CONFIG_SCSI_GENERIC_NCR5380 is not set # CONFIG_SCSI_GENERIC_NCR53C400 is not set -CONFIG_SCSI_G_NCR5380_PORT=y +# CONFIG_SCSI_G_NCR5380_PORT is not set # CONFIG_SCSI_G_NCR5380_MEM is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile b/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile index 5abf0a0d62..78f5314004 100644 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile @@ -13,7 +13,7 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ i386_ksyms.o i387.o evtchn.o pci-dma.o ifdef CONFIG_PCI -obj-y += pci-i386.o pci-pc.o pci-irq.o +obj-y += pci-i386.o pci-pc.o endif include $(TOPDIR)/Rules.make diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c deleted file mode 100644 index 96dcdde6b3..0000000000 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Low-Level PCI Access for i386 machines - * - * Copyright 1993, 1994 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * Drew@Colorado.EDU - * +1 (303) 786-7975 - * - * Drew's work was sponsored by: - * iX Multiuser Multitasking Magazine - * Hannover, Germany - * hm@ix.de - * - * Copyright 1997--2000 Martin Mares - * - * For more information, please consult the following manuals (look at - * http://www.pcisig.com/ for how to get them): - * - * PCI BIOS Specification - * PCI Local Bus Specification - * PCI to PCI Bridge Specification - * PCI System Design Guide - * - * - * CHANGELOG : - * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION - * Revision 2.0 present on 's ASUS mainboard. - * - * Jan 5, 1995 : Modified to probe PCI hardware at boot time by Frederic - * Potter, potter@cao-vlsi.ibp.fr - * - * Jan 10, 1995 : Modified to store the information about configured pci - * devices into a list, which can be accessed via /proc/pci by - * Curtis Varner, cvarner@cs.ucr.edu - * - * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter. - * Alpha version. Intel & UMC chipset support only. - * - * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code - * moved to drivers/pci/pci.c. - * - * Dec 7, 1996 : Added support for direct configuration access of boards - * with Intel compatible access schemes (tsbogend@alpha.franken.de) - * - * Feb 3, 1997 : Set internal functions to static, save/restore flags - * avoid dead locks reading broken PCI BIOS, werner@suse.de - * - * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS - * (mj@atrey.karlin.mff.cuni.cz) - * - * May 7, 1997 : Added some missing cli()'s. [mj] - * - * Jun 20, 1997 : Corrected problems in "conf1" type accesses. - * (paubert@iram.es) - * - * Aug 2, 1997 : Split to PCI BIOS handling and direct PCI access parts - * and cleaned it up... Martin Mares - * - * Feb 6, 1998 : No longer using BIOS to find devices and device classes. [mj] - * - * May 1, 1998 : Support for peer host bridges. [mj] - * - * Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space - * can be accessed from interrupts even on SMP systems. [mj] - * - * August 1998 : Better support for peer host bridges and more paranoid - * checks for direct hardware access. Ugh, this file starts to look as - * a large gallery of common hardware bug workarounds (watch the comments) - * -- the PCI specs themselves are sane, but most implementors should be - * hit hard with \hammer scaled \magstep5. [mj] - * - * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj] - * - * Feb 8, 1999 : Added UM8886BF I/O address fixup. [mj] - * - * August 1999 : New resource management and configuration access stuff. [mj] - * - * Sep 19, 1999 : Use PCI IRQ routing tables for detection of peer host bridges. - * Based on ideas by Chris Frantz and David Hinds. [mj] - * - * Sep 28, 1999 : Handle unreported/unassigned IRQs. Thanks to Shuu Yamaguchi - * for a lot of patience during testing. [mj] - * - * Oct 8, 1999 : Split to pci-i386.c, pci-pc.c and pci-visws.c. [mj] - */ - -#include -#include -#include -#include -#include -#include - -#include "pci-i386.h" - -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resource, - new, check); - } -} - -/* - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - * - * Why? Because some silly external IO cards only decode - * the low 10 bits of the IO address. The 0x00-0xff region - * is reserved for motherboard devices that decode all 16 - * bits, so it's ok to allocate at, say, 0x2800-0x28ff, - * but we want to try to avoid allocating at 0x2900-0x2bff - * which might have be mirrored at 0x0100-0x03ff.. - */ -void -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; - - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} - - -/* - * Handle resources of PCI devices. If the world were perfect, we could - * just allocate all the resource regions and do nothing more. It isn't. - * On the other hand, we cannot just re-allocate all devices, as it would - * require us to know lots of host bridge internals. So we attempt to - * keep as much of the original configuration as possible, but tweak it - * when it's found to be wrong. - * - * Known BIOS problems we have to work around: - * - I/O or memory regions not configured - * - regions configured, but not enabled in the command register - * - bogus I/O addresses above 64K used - * - expansion ROMs left enabled (this may sound harmless, but given - * the fact the PCI specs explicitly allow address decoders to be - * shared between expansion ROMs and other resource regions, it's - * at least dangerous) - * - * Our solution: - * (1) Allocate resources for all buses behind PCI-to-PCI bridges. - * This gives us fixed barriers on where we can allocate. - * (2) Allocate resources for all enabled devices. If there is - * a collision, just mark the resource as unallocated. Also - * disable expansion ROMs during this step. - * (3) Try to allocate resources for disabled devices. If the - * resources were assigned correctly, everything goes well, - * if they weren't, they won't disturb allocation of other - * resources. - * (4) Assign new addresses to resources which were either - * not configured at all or misconfigured. If explicitly - * requested by the user, configure expansion ROM address - * as well. - */ - -static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) -{ - struct list_head *ln; - struct pci_bus *bus; - struct pci_dev *dev; - int idx; - struct resource *r, *pr; - - /* Depth-First Search on bus tree */ - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { - bus = pci_bus_b(ln); - if ((dev = bus->self)) { - printk("alloc bus res: %s\n", dev->slot_name); - for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { - r = &dev->resource[idx]; - if (!r->start) - { - printk(" res1: 0x%08lx-0x%08lx f=%lx\n", - r->start, r->end, r->flags); - - continue; - } - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) - printk(KERN_ERR "PCI: Cannot allocate resource region %d " - "of bridge %s (%p)\n", idx, dev->slot_name, pr); - printk(" res2: %08lx-%08lx f=%lx\n", - r->start, r->end, r->flags); - } - } - pcibios_allocate_bus_resources(&bus->children); - } -} - -static void __init pcibios_allocate_resources(int pass) -{ - struct pci_dev *dev; - int idx, disabled; - u16 command; - struct resource *r, *pr; - - pci_for_each_dev(dev) { - pci_read_config_word(dev, PCI_COMMAND, &command); - for(idx = 0; idx < 6; idx++) { - r = &dev->resource[idx]; - if (r->parent) /* Already allocated */ - continue; - if (!r->start) /* Address not assigned at all */ - continue; - if (r->flags & IORESOURCE_IO) - disabled = !(command & PCI_COMMAND_IO); - else - disabled = !(command & PCI_COMMAND_MEMORY); - if (pass == disabled) { - printk("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d) (%s)\n", - r->start, r->end, r->flags, disabled, pass, dev->slot_name); - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) { - printk(KERN_ERR "PCI: Cannot allocate resource region %d" - " of device %s (%p)\n", idx, dev->slot_name, pr); - /* We'll assign a new address later */ - r->end -= r->start; - r->start = 0; - } - } - } - if (!pass) { - r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & PCI_ROM_ADDRESS_ENABLE) { - /* Turn the ROM off, leave the resource region, but keep it unregistered. */ - u32 reg; - printk("PCI: Switching off ROM of %s\n", dev->slot_name); - r->flags &= ~PCI_ROM_ADDRESS_ENABLE; - pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); - } - } - } -} - -static void __init pcibios_assign_resources(void) -{ - struct pci_dev *dev; - int idx; - struct resource *r; - - pci_for_each_dev(dev) { - int class = dev->class >> 8; - - /* Don't touch classless devices and host bridges */ - if (!class || class == PCI_CLASS_BRIDGE_HOST) - continue; - - for(idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - - /* - * Don't touch IDE controllers and I/O ports of video cards! - */ - if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) || - (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO))) - continue; - - /* - * We shall assign a new address to this resource, either because - * the BIOS forgot to do so or because we have decided the old - * address was unusable for some reason. - */ - if (!r->start && r->end) - pci_assign_resource(dev, idx); - } - - if (pci_probe & PCI_ASSIGN_ROMS) { - r = &dev->resource[PCI_ROM_RESOURCE]; - r->end -= r->start; - r->start = 0; - if (r->end) - pci_assign_resource(dev, PCI_ROM_RESOURCE); - } - } -} - -void __init pcibios_set_cacheline_size(void) -{ - struct cpuinfo_x86 *c = &boot_cpu_data; - - pci_cache_line_size = 32 >> 2; - if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD) - pci_cache_line_size = 64 >> 2; /* K7 & K8 */ - else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL) - pci_cache_line_size = 128 >> 2; /* P4 */ -} - -void __init pcibios_resource_survey(void) -{ - DBG("PCI: Allocating resources\n"); - pcibios_allocate_bus_resources(&pci_root_buses); - pcibios_allocate_resources(0); - pcibios_allocate_resources(1); - pcibios_assign_resources(); -} - -int pcibios_enable_resources(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for(idx=0; idx<6; idx++) { - /* Only set up the requested stuff */ - if (!(mask & (1<resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -/* - * If we set up a device for bus mastering, we need to check the latency - * timer as certain crappy BIOSes forget to set it properly. - */ -unsigned int pcibios_max_latency = 255; - -void pcibios_set_master(struct pci_dev *dev) -{ - u8 lat; - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - else - return; - printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -} - -int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine) -{ - unsigned long prot; - - /* I/O space cannot be accessed via normal processor loads and - * stores on this platform. - */ - if (mmap_state == pci_mmap_io) - return -EINVAL; - - /* Leave vm_pgoff as-is, the PCI space address is the physical - * address on this platform. - */ - vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO); - - prot = pgprot_val(vma->vm_page_prot); - if (boot_cpu_data.x86 > 3) - prot |= _PAGE_PCD | _PAGE_PWT; - vma->vm_page_prot = __pgprot(prot); - - /* Write-combine setting is ignored, it is changed via the mtrr - * interfaces on this platform. - */ - if (remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) - return -EAGAIN; - - return 0; -} diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h b/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h deleted file mode 100644 index fe70b10166..0000000000 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Low-Level PCI Access for i386 machines. - * - * (c) 1999 Martin Mares - */ - -#undef DEBUG - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -#define PCI_PROBE_BIOS 0x0001 -#define PCI_PROBE_CONF1 0x0002 -#define PCI_PROBE_CONF2 0x0004 -#define PCI_NO_SORT 0x0100 -#define PCI_BIOS_SORT 0x0200 -#define PCI_NO_CHECKS 0x0400 -#define PCI_ASSIGN_ROMS 0x1000 -#define PCI_BIOS_IRQ_SCAN 0x2000 -#define PCI_ASSIGN_ALL_BUSSES 0x4000 - -extern unsigned int pci_probe; - -/* pci-i386.c */ - -extern unsigned int pcibios_max_latency; -extern u8 pci_cache_line_size; - -void pcibios_resource_survey(void); -void pcibios_set_cacheline_size(void); -int pcibios_enable_resources(struct pci_dev *, int); - -/* pci-pc.c */ - -extern int pcibios_last_bus; -extern struct pci_bus *pci_root_bus; -extern struct pci_ops *pci_root_ops; - -/* pci-irq.c */ - -struct irq_info { - u8 bus, devfn; /* Bus, device and function */ - struct { - u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ - u16 bitmap; /* Available IRQs */ - } __attribute__((packed)) irq[4]; - u8 slot; /* Slot number, 0=onboard */ - u8 rfu; -} __attribute__((packed)); - -struct irq_routing_table { - u32 signature; /* PIRQ_SIGNATURE should be here */ - u16 version; /* PIRQ_VERSION */ - u16 size; /* Table size in bytes */ - u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ - u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ - u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ - u32 miniport_data; /* Crap */ - u8 rfu[11]; - u8 checksum; /* Modulo 256 checksum must give zero */ - struct irq_info slots[0]; -} __attribute__((packed)); - -extern unsigned int pcibios_irq_mask; - -void pcibios_irq_init(void); -void pcibios_fixup_irqs(void); -void pcibios_enable_irq(struct pci_dev *dev); diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c deleted file mode 100644 index f530244f6a..0000000000 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- - **************************************************************************** - * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge - **************************************************************************** - * - * File: phys_dev.c - * Author: Rolf Neugebauer (rolf.neugebauer@intel.com) - * Date: Mar 2004 - * - * Description: XenoLinux wrappers for PCI interrupt handling. - * very simple since someone else is doing all the hard bits - */ - - -/* - * Low-Level PCI Support for PC -- Routing of Interrupts - * - * (c) 1999--2000 Martin Mares - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "pci-i386.h" - -#include - -unsigned int pcibios_irq_mask = 0xfff8; - -void eisa_set_level_irq(unsigned int irq) -{ - /* dummy */ -} - -void __init pcibios_irq_init(void) -{ - printk("PCI: IRQ init\n"); -} - -void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev; - physdev_op_t op; - int ret; - - - printk("PCI: IRQ fixup\n"); - pci_for_each_dev(dev) { - - op.cmd = PHYSDEVOP_FIND_IRQ; - op.u.find_irq.seg = 0; - op.u.find_irq.bus = dev->bus->number; - op.u.find_irq.dev = PCI_SLOT(dev->devfn); - op.u.find_irq.func = PCI_FUNC(dev->devfn); - - if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 ) - { - printk(KERN_ALERT "pci find irq error\n"); - return; - } - - dev->irq = op.u.find_irq.irq; - printk(KERN_INFO "PCI IRQ: [%02x:%02x:%02x] -> %d\n", - dev->bus->number, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), dev->irq); - } - return; -} - -void pcibios_penalize_isa_irq(int irq) -{ - /* dummy */ -} - -void pcibios_enable_irq(struct pci_dev *dev) -{ - u8 pin; - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - - if (pin && !dev->irq) { - printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of " - "device %s.\n", 'A' + pin - 1, dev->slot_name); - } -} diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c index afe6e4d494..48dcecd6ec 100644 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c @@ -3,7 +3,8 @@ * * (c) 1999--2000 Martin Mares * - * adjusted to use Xen's interface by Rolf Neugebauer + * Adjusted to use Xen's interface by Rolf Neugebauer, Intel Research Cambridge + * Further modifications by Keir Fraser, University of Cambridge */ #include @@ -22,29 +23,28 @@ #include "pci-i386.h" -int pcibios_last_bus = -1; -struct pci_bus *pci_root_bus = NULL; -struct pci_ops *pci_root_ops = NULL; - -int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL; -int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL; - -static int pci_using_acpi_prt = 0; - /* - * This interrupt-safe spinlock protects all accesses to PCI - * configuration space. + * NB. The following interface functions are not included here: + * 1. void eisa_set_level_irq(unsigned int irq) + * 2. irq_routing_table * __devinit pcibios_get_irq_routing_table(void) + * 3. int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq) + * All are used by the ACPI driver. This should be ported to Xen if it is + * ever required -- Xen is the ultimate source for IRQ-routing knowledge. */ -static spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED; + +struct pci_ops *pci_root_ops = NULL; + +int (*pci_config_read)(int seg, int bus, int dev, int fn, + int reg, int len, u32 *value) = NULL; +int (*pci_config_write)(int seg, int bus, int dev, int fn, + int reg, int len, u32 value) = NULL; unsigned int pci_probe = PCI_PROBE_BIOS; -/* - * Functions for accessing PCI configuration space with type 1 accesses - */ +struct pci_fixup pcibios_fixups[] = { { 0 } }; -static int pci_confx_read (int seg, int bus, int dev, int fn, int reg, - int len, u32 *value) +static int pci_confx_read(int seg, int bus, int dev, int fn, int reg, + int len, u32 *value) { int ret; physdev_op_t op; @@ -52,27 +52,23 @@ static int pci_confx_read (int seg, int bus, int dev, int fn, int reg, if (bus > 255 || dev > 31 || fn > 7 || reg > 255) return -EINVAL; - op.cmd = PHYSDEVOP_CFGREG_READ; - op.u.cfg_read.seg = seg; - op.u.cfg_read.bus = bus; - op.u.cfg_read.dev = dev; - op.u.cfg_read.func = fn; - op.u.cfg_read.reg = reg; - op.u.cfg_read.len = len; + op.cmd = PHYSDEVOP_PCI_CFGREG_READ; + op.u.pci_cfgreg_read.bus = bus; + op.u.pci_cfgreg_read.dev = dev; + op.u.pci_cfgreg_read.func = fn; + op.u.pci_cfgreg_read.reg = reg; + op.u.pci_cfgreg_read.len = len; if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 ) - { - //printk(KERN_ALERT "pci config read error\n"); return ret; - } - *value = op.u.cfg_read.value; + *value = op.u.pci_cfgreg_read.value; return 0; } -static int pci_confx_write (int seg, int bus, int dev, int fn, int reg, - int len, u32 value) +static int pci_confx_write(int seg, int bus, int dev, int fn, int reg, + int len, u32 value) { int ret; physdev_op_t op; @@ -80,25 +76,22 @@ static int pci_confx_write (int seg, int bus, int dev, int fn, int reg, if ((bus > 255 || dev > 31 || fn > 7 || reg > 255)) return -EINVAL; - op.cmd = PHYSDEVOP_CFGREG_WRITE; - op.u.cfg_write.seg = seg; - op.u.cfg_write.bus = bus; - op.u.cfg_write.dev = dev; - op.u.cfg_write.func = fn; - op.u.cfg_write.reg = reg; - op.u.cfg_write.len = len; - op.u.cfg_write.value = value; + op.cmd = PHYSDEVOP_PCI_CFGREG_WRITE; + op.u.pci_cfgreg_write.bus = bus; + op.u.pci_cfgreg_write.dev = dev; + op.u.pci_cfgreg_write.func = fn; + op.u.pci_cfgreg_write.reg = reg; + op.u.pci_cfgreg_write.len = len; + op.u.pci_cfgreg_write.value = value; if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 ) - { - //printk(KERN_ALERT "pci config write error\n"); return ret; - } return 0; } -static int pci_confx_read_config_byte(struct pci_dev *dev, int where, u8 *value) +static int pci_confx_read_config_byte(struct pci_dev *dev, + int where, u8 *value) { int result; u32 data; @@ -111,7 +104,8 @@ static int pci_confx_read_config_byte(struct pci_dev *dev, int where, u8 *value) return result; } -static int pci_confx_read_config_word(struct pci_dev *dev, int where, u16 *value) +static int pci_confx_read_config_word(struct pci_dev *dev, + int where, u16 *value) { int result; u32 data; @@ -124,31 +118,35 @@ static int pci_confx_read_config_word(struct pci_dev *dev, int where, u16 *value return result; } -static int pci_confx_read_config_dword(struct pci_dev *dev, int where, u32 *value) +static int pci_confx_read_config_dword(struct pci_dev *dev, + int where, u32 *value) { return pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 4, value); } -static int pci_confx_write_config_byte(struct pci_dev *dev, int where, u8 value) +static int pci_confx_write_config_byte(struct pci_dev *dev, + int where, u8 value) { return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 1, value); } -static int pci_confx_write_config_word(struct pci_dev *dev, int where, u16 value) +static int pci_confx_write_config_word(struct pci_dev *dev, + int where, u16 value) { return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 2, value); } -static int pci_confx_write_config_dword(struct pci_dev *dev, int where, u32 value) +static int pci_confx_write_config_dword(struct pci_dev *dev, + int where, u32 value) { return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 4, value); } -static struct pci_ops pci_direct_confx = { +static struct pci_ops pci_conf_xen = { pci_confx_read_config_byte, pci_confx_read_config_word, pci_confx_read_config_dword, @@ -157,129 +155,14 @@ static struct pci_ops pci_direct_confx = { pci_confx_write_config_dword }; - - -static struct pci_ops * __devinit pci_check_xen(void) -{ - unsigned long flags; - - __save_flags(flags); __cli(); - - printk(KERN_INFO "PCI: Using Xen interface\n"); - - __restore_flags(flags); - - return &pci_direct_confx; -} - -struct pci_fixup pcibios_fixups[] = { {0}}; - - -struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void) -{ - return NULL; -} - -int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq) -{ - return 0; +void pcibios_penalize_isa_irq(int irq) +{ + /* nothing */ } -/* - * Several buggy motherboards address only 16 devices and mirror - * them to next 16 IDs. We try to detect this `feature' on all - * primary buses (those containing host bridges as they are - * expected to be unique) and remove the ghost devices. - */ - -static void __devinit pcibios_fixup_ghosts(struct pci_bus *b) +void __devinit pcibios_fixup_bus(struct pci_bus *b) { - struct list_head *ln, *mn; - struct pci_dev *d, *e; - int mirror = PCI_DEVFN(16,0); - int seen_host_bridge = 0; - int i; - - DBG("PCI: Scanning for ghost devices on bus %d\n", b->number); - for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { - d = pci_dev_b(ln); - if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST) - seen_host_bridge++; - for (mn=ln->next; mn != &b->devices; mn=mn->next) { - e = pci_dev_b(mn); - if (e->devfn != d->devfn + mirror || - e->vendor != d->vendor || - e->device != d->device || - e->class != d->class) - continue; - for(i=0; iresource[i].start != d->resource[i].start || - e->resource[i].end != d->resource[i].end || - e->resource[i].flags != d->resource[i].flags) - continue; - break; - } - if (mn == &b->devices) - return; - } - if (!seen_host_bridge) - return; - printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number); - - ln = &b->devices; - while (ln->next != &b->devices) { - d = pci_dev_b(ln->next); - if (d->devfn >= mirror) { - list_del(&d->global_list); - list_del(&d->bus_list); - kfree(d); - } else - ln = ln->next; - } -} - -/* - * Discover remaining PCI buses in case there are peer host bridges. - * We use the number of last PCI bus provided by the PCI BIOS. - */ -static void __devinit pcibios_fixup_peer_bridges(void) -{ - int n; - struct pci_bus bus; - struct pci_dev dev; - u16 l; - - if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) - return; - DBG("PCI: Peer bridge fixup\n"); - for (n=0; n <= pcibios_last_bus; n++) { - if (pci_bus_exists(&pci_root_buses, n)) - continue; - bus.number = n; - bus.ops = pci_root_ops; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn<256; dev.devfn += 8) - if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) && - l != 0x0000 && l != 0xffff) { - DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l); - printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); - pci_scan_bus(n, pci_root_ops, NULL); - break; - } - } -} - - -/* - * Called after each bus is probed, but before its children - * are examined. - */ - -void __devinit pcibios_fixup_bus(struct pci_bus *b) -{ - pcibios_fixup_ghosts(b); pci_read_bridge_bases(b); - return; } struct pci_bus * __devinit pcibios_scan_root(int busnum) @@ -287,78 +170,91 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum) struct list_head *list; struct pci_bus *bus; - list_for_each(list, &pci_root_buses) { + list_for_each ( list, &pci_root_buses ) + { bus = pci_bus_b(list); - if (bus->number == busnum) { - /* Already scanned */ + if ( bus->number == busnum ) return bus; - } } printk("PCI: Probing PCI hardware (bus %02x)\n", busnum); - return pci_scan_bus(busnum, pci_root_ops, NULL); } -void __devinit pcibios_config_init(void) +void __init pcibios_init(void) { - /* - * Try all known PCI access methods. Note that we support using - * both PCI BIOS and direct access, with a preference for direct. - */ + int bus; + physdev_op_t op; + + if ( !pci_probe ) + return; - pci_root_ops = pci_check_xen(); - pci_config_read = pci_confx_read; + pci_root_ops = &pci_conf_xen; + pci_config_read = pci_confx_read; pci_config_write = pci_confx_write; - return; -} + pcibios_set_cacheline_size(); -void __init pcibios_init(void) -{ - if (!pci_root_ops) - pcibios_config_init(); - if (!pci_root_ops) { + op.cmd = PHYSDEVOP_PCI_PROBE_ROOT_BUSES; + if ( HYPERVISOR_physdev_op(&op) != 0 ) + { printk(KERN_WARNING "PCI: System does not support PCI\n"); return; } - pcibios_set_cacheline_size(); - printk(KERN_INFO "PCI: Probing PCI hardware\n"); - - if (!pci_using_acpi_prt) { - pci_root_bus = pcibios_scan_root(0); - pcibios_irq_init(); - pcibios_fixup_peer_bridges(); - pcibios_fixup_irqs(); - } + for ( bus = 0; bus < 256; bus++ ) + if ( test_bit(bus, &op.u.pci_probe_root_buses.busmask[0]) ) + (void)pcibios_scan_root(bus); pcibios_resource_survey(); } -char * __devinit pcibios_setup(char *str) +char * __devinit pcibios_setup(char *str) { - if (!strcmp(str, "off")) { + if ( !strcmp(str, "off") ) pci_probe = 0; - return NULL; - } return NULL; } unsigned int pcibios_assign_all_busses(void) { - return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; + return 0; } int pcibios_enable_device(struct pci_dev *dev, int mask) { int err; + u8 pin; + physdev_op_t op; - if ((err = pcibios_enable_resources(dev, mask)) < 0) + /* Inform Xen that we are going to use this device. */ + op.cmd = PHYSDEVOP_PCI_INITIALISE_DEVICE; + op.u.pci_initialise_device.bus = dev->bus->number; + op.u.pci_initialise_device.dev = PCI_SLOT(dev->devfn); + op.u.pci_initialise_device.func = PCI_FUNC(dev->devfn); + if ( (err = HYPERVISOR_physdev_op(&op)) != 0 ) return err; - pcibios_enable_irq(dev); + /* Now we can bind to the very final IRQ line. */ + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &pin); + dev->irq = pin; + + /* Turn on device I/O and memory access as necessary. */ + if ( (err = pcibios_enable_resources(dev, mask)) < 0 ) + return err; + + /* Sanity-check that an interrupt-producing device is routed to an IRQ. */ + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if ( pin != 0 ) + { + if ( dev->irq != 0 ) + printk(KERN_INFO "PCI: Obtained IRQ %d for device %s\n", + dev->irq, dev->slot_name); + else + printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of " + "device %s.\n", 'A' + pin - 1, dev->slot_name); + } return 0; } diff --git a/xenolinux-2.4.25-sparse/mkbuildtree b/xenolinux-2.4.25-sparse/mkbuildtree index b6679d05df..faaf923c30 100755 --- a/xenolinux-2.4.25-sparse/mkbuildtree +++ b/xenolinux-2.4.25-sparse/mkbuildtree @@ -200,6 +200,9 @@ ln -sf ../asm-i386/user.h cd ../../arch/xen/kernel ln -sf ../../i386/kernel/i387.c ln -sf ../../i386/kernel/init_task.c +ln -sf ../../i386/kernel/pci-dma.c +ln -sf ../../i386/kernel/pci-i386.c +ln -sf ../../i386/kernel/pci-i386.h ln -sf ../../i386/kernel/ptrace.c ln -sf ../../i386/kernel/semaphore.c ln -sf ../../i386/kernel/sys_i386.c